package com.fdb.efp.cus.api.rest;

import java.io.*;
import java.nio.charset.Charset;
import java.util.*;
import java.util.stream.Collectors;
//import java.util.Map;

//import com.fdb.basic.framework.core.constant.DataRuleType;
//import com.fdb.basic.framework.core.constant.PubConstant;
import com.alibaba.fastjson.JSON;
import com.gdrcu.efp.cus.common.ExcelException;
import com.gdrcu.efp.cus.common.util.ExcelImportUtil;
import com.fdb.basic.framework.core.constant.ApplicationConstance;
import com.fdb.basic.framework.core.constant.ResponseData;
import com.fdb.basic.framework.core.constant.SDicCertTypeEnum;
import com.fdb.basic.framework.core.exception.BizException;
import com.fdb.basic.framework.core.util.MessageRuleCheckUtil;
import com.fdb.basic.framework.core.util.StringUtil;
import com.fdb.basic.framework.core.util.TimeUtil;
import com.fdb.basic.framework.core.util.UUIDUtil;
import com.fdb.basic.framework.web.controller.AbstractController;
import com.fdb.basic.sequence.service.facade.SequenceService;
import com.fdb.efp.cus.service.facade.BlackListInfoService;
import com.fdb.efp.cus.service.vo.BlackListInfoExcelVO;
import com.fdb.efp.cus.service.vo.BlackListInfoVO;
//import com.fdb.efp.e4a.service.facade.SRoleDataRuleService;
//import com.fdb.efp.cus.service.vo.CusRelCheckVO;
import com.fdb.efp.cus.service.vo.CusWhiteListTecExcelVO;
import com.fdb.efp.cus.service.vo.CusWhiteListTecVO;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@RestController
@RequestMapping("/api")
public class BlackListInfoController extends AbstractController {

	@Autowired
	@Qualifier("blackListInfoService")
	private BlackListInfoService blackListInfoService;
//	@Autowired
//	@Qualifier("sRoleDataRuleService")
//	private SRoleDataRuleService sRoleDataRuleService;

	@Autowired
	@Qualifier("dbSeqService")
	private SequenceService sequenceService;

	private static Logger logger = LoggerFactory.getLogger(BlackListInfoController.class);
	private static final String CONTENTTYPE = "application/json;charset=UTF-8";
	private static final String MODELNAME = "黑名单信息模板.xls";
	private static final String SHEET1NAME = "黑名单";
	private static final String IMPORT_PATH = "/template/importBlackListInfo.xls";
	private List<BlackListInfoExcelVO> errorHisDuplicateDataList = new ArrayList<>();
	private List<BlackListInfoExcelVO> singleRowList = new ArrayList<>();

	/**
	 * 列表数据查询
	 *
	 * @param page
	 * @param size
	 * @return
	 */
	@RequestMapping(value = "/black/list/infos", method = RequestMethod.POST)
	public @ResponseBody
	ResponseData<List<BlackListInfoVO>> queryBlackListInfoAll(
			@RequestBody BlackListInfoVO vo) {
		List<BlackListInfoVO> outputVo = blackListInfoService.queryAllOwner(vo);
//		Map<String,String> dataRuleTypeMap = sRoleDataRuleService.getDataRuleType(httpRequest.getRequestURI(), getUserRoles());
//		vo.setPrdCodebyBaseInfo(dataRuleTypeMap == null ? null:dataRuleTypeMap.get(PubConstant.PRD_CODE));
//		DataRuleType dataRuleType = DataRuleType.getDataRuleType(dataRuleTypeMap == null ? null:dataRuleTypeMap.get(PubConstant.PERMIS_TYPE));
//		setUserInfoToVO(vo);
//		// 根据权限方案调用不同的方案进行数据查询
//		switch (dataRuleType) {
//			case Owner:
//				outputVo = blackListInfoService.queryAllOwner(vo);
//				break;
//			case CurrOrg:
//				outputVo = blackListInfoService.queryAllCurrOrg(vo);
//				break;
//			case CurrDownOrg:
//				outputVo = blackListInfoService.queryAllCurrDownOrg(vo);
//				break;
////			case CurrOwnerPrd:
////				outputVo = blackListInfoService.queryAllCurrOwnerPrd(vo);
////				break;
//			default:
//				outputVo = blackListInfoService.queryAllCurrOrg(vo);
//				break;
//		}
		return getResponseData(outputVo);

	}

	/**
	 * 根据主键查询详情
	 *
	 * @return
	 */
	@RequestMapping(value = "/black/list/info", method = RequestMethod.GET)
	public @ResponseBody
	ResponseData<BlackListInfoVO> queryByPk() {
		BlackListInfoVO inVo = new BlackListInfoVO();
		BlackListInfoVO outputVo = blackListInfoService.queryByPk(inVo);
		return getResponseData(outputVo);

	}

	/**
	 * 根据主键删除信息
	 *
	 * @param blackListInfo
	 * @return
	 */
	@RequestMapping(value = "/black/list/info", method = RequestMethod.DELETE)
	public @ResponseBody
	ResponseData<Integer> deleteByPk(@RequestBody BlackListInfoVO inBlackListInfoVo) {
		int outputVo = blackListInfoService.deleteByPk(inBlackListInfoVo);
		return getResponseData(outputVo);

	}

	/**
	 * 根据主键更新信息
	 *
	 * @param inBlackListInfoVo
	 * @return
	 */
	@RequestMapping(value = "/black/list/info", method = RequestMethod.PUT)
	public @ResponseBody
	ResponseData<Integer> updateByPk(@RequestBody BlackListInfoVO inBlackListInfoVo) {
		setUserInfoToVO(inBlackListInfoVo);
		List<BlackListInfoVO> tempVo = blackListInfoService.queryByCertCodeAndType(inBlackListInfoVo);
		if (Objects.nonNull(tempVo)) {
			ResponseData<Integer> responseData = new ResponseData<Integer>();
			responseData.setMessage("证件号码是：【" + inBlackListInfoVo.getCertCode() + "】的黑名单信息已存在！");
			responseData.setCode(ApplicationConstance.FAILURE);
			responseData.setSuccess(false);
			return responseData;
		}
		inBlackListInfoVo.setLastChgUsr(inBlackListInfoVo.getLoginUserId());
		inBlackListInfoVo.setLastChgTime(TimeUtil.getCurrentDateTime());
		int outputVo = blackListInfoService.updateByPk(inBlackListInfoVo);
		return getResponseData(outputVo);

	}

	/**
	 * 新增数据
	 *
	 * @param inBlackListInfoVo
	 * @return
	 */
	@RequestMapping(value = "/black/list/info", method = RequestMethod.POST)
	public @ResponseBody
	ResponseData<Integer> insertBlackListInfo(@RequestBody BlackListInfoVO inBlackListInfoVo) {
		setUserInfoToVO(inBlackListInfoVo);
		List<BlackListInfoVO> tempVo = blackListInfoService.queryByCertCodeAndType(inBlackListInfoVo);
		if (Objects.nonNull(tempVo)) {
			ResponseData<Integer> responseData = new ResponseData<Integer>();
			responseData.setMessage("证件号码是：【" + inBlackListInfoVo.getCertCode() + "】的黑名单信息已存在！");
			responseData.setCode(ApplicationConstance.FAILURE);
			responseData.setSuccess(false);
			return responseData;
		}
		inBlackListInfoVo.setBlackId(UUIDUtil.getUUID());
		inBlackListInfoVo.setCreateUser(inBlackListInfoVo.getLoginUserId());
		inBlackListInfoVo.setCreateTime(TimeUtil.getCurrentDateTime());
		int outputVo = blackListInfoService.insertBlackListInfo(inBlackListInfoVo);
		return getResponseData(outputVo);

	}

	/**
	 * 黑名单模板下载
	 *
	 * @param inBlackListInfoVo
	 * @return
	 */

	@RequestMapping(value = "/black/list/downLoad", method = RequestMethod.GET)
	public @ResponseBody
	ResponseData<String> blackListInfoModelDownLoad(HttpServletResponse response, HttpServletRequest request) throws IOException {
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		try {
			response.setContentType(CONTENTTYPE);
			/**
			 * getBytes()，需要声明一下读取的编码方式，不然IE浏览器，会出现文件名乱码，谷歌不会
			 * 【解决方法】 getBytes("GBK")
			 */
			response.setHeader("Content-Disposition", "attachment;filename=" + new String((MODELNAME).getBytes("GBK"), "ISO8859-1"));
			ServletOutputStream out = response.getOutputStream();
			logger.info("下载黑名单数据数据导入模板开始----------------------------");
			bis = new BufferedInputStream(BlackListInfoController.class.getClassLoader().getResourceAsStream(IMPORT_PATH));
			bos = new BufferedOutputStream(out);
			byte[] buff = new byte[2048];
			int bytesRead;
			while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
				bos.write(buff, 0, bytesRead);
			}
		} catch (Exception e) {
			logger.error("黑名单列表数据模板文件下载失败：", e);
			return getResponseData(null);
		} finally {
			if (null != bis) {
				bis.close();
			}
			if (null != bos) {
				bos.close();
			}
		}
		logger.info("下载黑名单列表数据导入模板结束。。。。。。。。。。。。。。。。。。。");
		return getResponseData("success!");
	}

	/**
	 * 文件导入并解析储存到数据表
	 */
	@SuppressWarnings("resource")
	@RequestMapping(value = "/black/list/upload", method = RequestMethod.POST)
	public void blackListInfoListUpload(HttpServletResponse respone, HttpServletRequest request) {
		ResponseData<List<BlackListInfoVO>> result = new ResponseData<List<BlackListInfoVO>>();
		List<File> blackListInfoVOChecks = new ArrayList<File>();
		respone.setContentType(CONTENTTYPE);
		OutputStream out = null;

		try {
			out = respone.getOutputStream();
			//获取文件
			blackListInfoVOChecks = getFileList(request);
			if (!blackListInfoVOChecks.isEmpty()) {
				for (File file : blackListInfoVOChecks) {
					/**
					 * 将Excel文件解析成对应实体Bean
					 */
					List<BlackListInfoExcelVO> blackListInfoExcelVO = ExcelImportUtil.importExcelByClass(SHEET1NAME, file, BlackListInfoExcelVO.class);
					//检查导入的数据是否填写错误
//					checkExcelDatas(cusWhiteListTecExcelVO);
					//检查历史数据是否重复
					String errStr = "";
					errStr = checkHisDatas(blackListInfoExcelVO);
					//组装数据
					List<BlackListInfoVO> inserBlackListInfo = new ArrayList<BlackListInfoVO>();
					inserBlackListInfo = assembleData(singleRowList);
					//执行插入操作
					int num = 0;
					if (inserBlackListInfo.size() > 0) num = execBatchInsertSql(inserBlackListInfo);
					if (num < 0) throw new Exception("插入数据出错！");
					//错误信息
					if (!StringUtil.isNullorBank(errStr)) {
						errStr = "ExcelError:" + errStr;
						throw new Exception(errStr);
					}
					//组装结果
					result = getResponseData(inserBlackListInfo);
				}
			} else {
				throw new ExcelException("获取不到上传的文件！");
			}
		} catch (Exception e) {
			logger.error("文件上传失败,失败原因:", e.getMessage());
			result = result.createData(null, ApplicationConstance.FAILURE, e.getMessage(), false);
		} finally {
			String str = JSON.toJSONString(result);
			try {
				out.write(str.getBytes(Charset.forName("UTF-8")));
				out.flush();
				out.close();
			} catch (IOException e) {
				logger.error("关闭数据流OutputStream出错，错误信息为：", e);
			}
		}
	}


	private int execBatchInsertSql(List<BlackListInfoVO> inserBlackListInfo) {
		int num = 0;
		return num = blackListInfoService.insertBlackListInfoBatch(inserBlackListInfo);
	}

	private List<BlackListInfoVO> assembleData(List<BlackListInfoExcelVO> blackListInfoExcelVO) throws ExcelException {
		List<BlackListInfoVO> list = new ArrayList<>();
		if (Objects.nonNull(blackListInfoExcelVO)) {
			Iterator<BlackListInfoExcelVO> iterator = blackListInfoExcelVO.iterator();
			while (iterator.hasNext()) {
				BlackListInfoExcelVO tempExcelVO = iterator.next();
				setUserInfoToVO(tempExcelVO);
				BlackListInfoVO tempVO = new BlackListInfoVO();
				tempVO.setBlackId(UUIDUtil.getUUID());
				tempVO.setName(tempExcelVO.getName());
				tempVO.setCertType(tempExcelVO.getCertType());
				tempVO.setCertCode(tempExcelVO.getCertCode());
				tempVO.setBlackListType(tempExcelVO.getBlackListType());
		        	tempVO.setCreateUser(tempExcelVO.getLoginUserId());
				tempVO.setCreateTime(TimeUtil.getCurrentDateTime());
				list.add(tempVO);
			}
		} else {
			throw new ExcelException("获取数据为空!");
		}
		return list;
	}

	private String checkHisDatas(List<BlackListInfoExcelVO> blackListInfoExcelVO) throws Exception {
		int errorRow = 4;
		List<Integer> errorDuplicateRowList = new ArrayList<>();
		String errorDuplicateMsg = "";
		errorHisDuplicateDataList.clear();
		Map<Integer, String> errorList = new HashMap<Integer, String>();

		for (BlackListInfoExcelVO item : blackListInfoExcelVO) {
			boolean flag = checkDataIsUnique(item);
			if (flag) {
				errorDuplicateRowList.add(errorRow);
				errorHisDuplicateDataList.add(item);
			}
			errorRow += 1;
		}

		//收集没问题的导入数据
		singleRowList.clear();
		singleRowList = blackListInfoExcelVO.stream().filter(a->!errorHisDuplicateDataList.contains(a)).collect(Collectors.toList());

		if (errorDuplicateRowList.size() > 0) {
			for (Integer integer : errorDuplicateRowList) {
				errorDuplicateMsg =  "第【" + integer + "】行，该客户已存在，跳过该条数据！";
				errorList.put(integer, errorDuplicateMsg);
			}
		}

		//按key值对errorList排序并将value拼接成字符串
		String rs = "";
		rs += sortAndSpliceMap(errorList);
		return rs;
//		if (!StringUtil.isNullorBank(rs)) {
//			rs = "DataDuplicateError:" + rs;
//			throw new Exception(rs);
//		}
	}

	private String sortAndSpliceMap(Map<Integer, String> errorList) {
		String rs = "";
		//取出key值，根据key值排序
		Object[] key = errorList.keySet().toArray();
		Arrays.sort(key);
		//拼接信息
		Iterator ite = errorList.entrySet().iterator();
		while (ite.hasNext()) {
			Map.Entry string = (Map.Entry) ite.next();
			StringBuffer buffer = new StringBuffer();
			if (StringUtil.isNullorBank(rs)) {
				rs = (String) string.getValue();
			} else {
				rs = buffer.append(rs).append(",").append(string.getValue()).toString();
			}
		}
		return rs;
	}

	private boolean checkDataIsUnique(BlackListInfoExcelVO item) {
		BlackListInfoVO blackListInfoVO = new BlackListInfoVO();
		blackListInfoVO.setCertType(item.getCertType());
		blackListInfoVO.setCertCode(item.getCertCode());
		List<BlackListInfoVO> queryRs = blackListInfoService.queryByCertCodeAndType(blackListInfoVO);
		return Objects.isNull(queryRs) ? false : true;
	}


	private void checkExcelDatas(List<CusWhiteListTecExcelVO> cusWhiteListTecExcelVO) {

	}

	/**
	 * 从HttpServletRequest中获取文件
	 */
	@SuppressWarnings("rawtypes")
	private List<File> getFileList(HttpServletRequest request) throws IOException{
		List<File> listFiles = new ArrayList<File>();
		CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
		if(multipartResolver.isMultipart(request)){
			MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
			Iterator iter = multiRequest.getFileNames();
			while(iter.hasNext()) {
				MultipartFile mFile = multiRequest.getFile(iter.next().toString());
				if(mFile != null){
					listFiles.add(multipartToFile(mFile));
				}
			}
		}
		return listFiles;
	}

	/**
	 * 转换文件
	 */
	private File multipartToFile(MultipartFile multfile) throws IOException {
		CommonsMultipartFile cmf = (CommonsMultipartFile)multfile;
		DiskFileItem dfi = (DiskFileItem) cmf.getFileItem();
		File file = dfi.getStoreLocation();
		if(file.length() < 2048){
			File tmpFile = new File(System.getProperty("java.io.tmpdir") + System.getProperty("file.separator") +  file.getName());
			multfile.transferTo(tmpFile);
			return tmpFile;
		}
		return file;
	}

	/**
	 * 批量删除信息
	 *
	 * @param blackListInfo
	 * @return
	 */
	@RequestMapping(value = "/black/list/info/batch", method = RequestMethod.DELETE)
	public @ResponseBody
	ResponseData<Integer> batchDeleteByPk(@RequestBody BlackListInfoVO inBlackListInfoVo) {
		int outputVo = blackListInfoService.batchDeleteByPk(inBlackListInfoVo);
		return getResponseData(outputVo);

	}

}
